<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// | 该文件的开源协议以所在项目的LICENSE文件为准，请遵守开源协议要求
// +----------------------------------------------------------------------
// | 流水记录
// +----------------------------------------------------------------------
namespace app\finance\model;

use Inphp\Core\Db\PDO\Model;
use Inphp\Core\Modules;

class BalanceHistoryModel extends Model
{
    /**
     * 表名
     * @var string
     */
    protected string $tableName = "finance_balanceHistory";

    /**
     * 主键
     * @var string
     */
    protected string $primaryKey = "id";

    /**
     * 字段数据
     * @var array
     */
    protected array $data = [
        //用户UID
        "uid"       => 0,
        //资产名称
        "name"      => null,
        //变动金额
        "amount"    => null,
        //剩余金额
        "balance"   => null,
        //变动代码
        "code"      => null,
        //备注
        "log"       => null,
        //编号人UID
        "editor"    => 0,
        //关联单号
        "linkId"    => 0
    ];

    /**
     * 设置字段
     * @param string $name
     * @param mixed $value
     */
    public function __set(string $name, mixed $value)
    {
        if (in_array($name, array_keys($this->data))) {
            $this->data[$name] = $value;
        }
    }

    /**
     * 签名加密字符串
     * 模块使用之初，可以自行设置，但请勿后期变更，否则无法解密
     * @var string
     */
    private string $signKey = "a4b5c6";

    /**
     * 保存
     */
    public function save(): bool
    {
        //如果开启了签名，则会自动校验历史
        $config = Modules::getModule("finance")->getConfig("history");
        if ($config["sign"]) {
            $this->signKey = $config["signKey"] ?? $this->signKey;
            $row = $this->getLastRow($this->data["uid"]);
            if (!empty($row) && !$this->verify($row)) {
                return false;
            }
        }
        //签名保存
        return self::emptyQuery()->insert($this->sign($this->data));
    }

    /**
     * 获取最后一条记录
     * @param int $uid
     * @return array
     */
    public function getLastRow(int $uid): array
    {
        $row = self::emptyQuery()
            ->where("uid", $uid)
            ->orderBy("id", "desc")
            ->first();
        return !empty($row) ? $row : [];
    }

    /**
     * 校验
     * @param array $row
     * @return bool
     */
    public function verify(array $row): bool
    {
        return $row["sign"] == $this->sign($row, true);
    }

    /**
     * 签名
     * @param array $data
     * @param bool $returnSign
     * @return array|string
     */
    public function sign(array $data, bool $returnSign = false): array|string
    {
        if ($this->signKey == "a4b5c6") {
            //如果没有设置不同的KEY，重新获取一次
            $config = Modules::getModule("finance")->getConfig("history");
            $this->signKey = $config["signKey"] ?? $this->signKey;
        }
        $strings = [];
        //排序
        ksort($data);
        $keys = array_keys($this->data);
        foreach ($data as $key => $val) {
            if (in_array($key, $keys)) {
                $val = is_numeric($val) ? floatval($val) : $val;
                $strings[] = "{$key}=>{$val}";
            }
        }
        $string = join("&", $strings);
        $sign = hash_hmac("md5", $string, $this->signKey);
        $data["sign"] = $sign;
        return $returnSign ? $sign : $data;
    }

    public static function translateCode(string $code) {
        $codes = Modules::getModule("finance")->getConfig("history.codes");
        return $codes[$code] ?? $code;
    }

}